﻿using System;
using System.Collections.Generic;

#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Media;
#else
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
#endif

namespace FreshMeat.Xaml
{
   public static class VisualHelper
   {
      /// <summary>
      /// Finds elements within a container that intersect a point.
      /// </summary>
      /// <param name="container">The container to search for intersecting elements.</param>
      /// <param name="point">A point in the container's coordinate system (0,0 is upper left corner of container).</param>
      /// <returns>Intersecting elements, if any.</returns>
      public static IEnumerable<UIElement> FindIntersectingElements(UIElement container, Point point)
      {
         //const double hitTestTolerance = 2.0;
         //var rect = new Rect(point.X - hitTestTolerance, point.Y - hitTestTolerance, hitTestTolerance * 2, hitTestTolerance * 2);
#if NETFX_CORE
         var transform = container.TransformToVisual(Window.Current.Content);
         var containerUpperLeft = transform.TransformPoint(new Point(0, 0));
         point.X += containerUpperLeft.X;
         point.Y += containerUpperLeft.Y;
         return VisualTreeHelper.FindElementsInHostCoordinates(point, container);
#elif SILVERLIGHT
         var transform = container.TransformToVisual(Application.Current.RootVisual);
         var containerUpperLeft = transform.Transform(new Point(0, 0));
         point.X += containerUpperLeft.X;
         point.Y += containerUpperLeft.Y;
         return VisualTreeHelper.FindElementsInHostCoordinates(point, container);
#else
         var list = new List<UIElement>();
         VisualTreeHelper.HitTest(
            container,
            filter => HitTestFilterBehavior.Continue,
            result =>
            {
               var element = result.VisualHit as UIElement;
               if (element != null)
                  list.Add(element);
               return HitTestResultBehavior.Continue;
            },
            new PointHitTestParameters(point));
         return list;
#endif
      }

      /// <summary>
      /// Generates a visual snapshop of an element.
      /// </summary>
      /// <param name="element"></param>
      /// <returns></returns>
      public static Image GenerateVisual(UIElement element)
      {
         if (element is ContentPresenter)
         {
            element = (UIElement)VisualTreeHelper.GetChild(element, 0);
            //element = ((UIElement)((ItemsGridItem)element).Content);
         }

#if NETFX_CORE
         var pixelWidth = (int)element.RenderSize.Width;
         var pixelHeight = (int)element.RenderSize.Height;
         var bitmap = new WriteableBitmap(pixelWidth, pixelHeight);
         // TODO: Figure out how to render the element into the bitmap for NETFX_CORE
#elif SILVERLIGHT
         var bitmap = new WriteableBitmap(element, new TranslateTransform());
#else
         var pixelWidth = (int)element.RenderSize.Width;
         var pixelHeight = (int)element.RenderSize.Height;
         var bitmap = new RenderTargetBitmap(pixelWidth, pixelHeight, 96, 96, PixelFormats.Pbgra32);
         bitmap.Render(element);
#endif
         var image = new Image { Source = bitmap, Stretch = Stretch.None };
         return image;
      }

      public static FrameworkElement GetRoot(DependencyObject item)
      {
         if (item == null)
            throw new ArgumentNullException("item");

         do
         {
            var parent = VisualTreeHelper.GetParent(item);
            if (parent == null)
               return item as FrameworkElement;

            item = parent;
         } while (true);
      }

#if !SILVERLIGHT && !NETFX_CORE
      public static Window GetWindow(DependencyObject item)
      {
         if (item == null)
            throw new ArgumentNullException("item");

         do
         {
            var root = GetRoot(item);
            if (root.Parent == null)
               return (Window)root;

            item = root.Parent;
         } while (true);
      }

      public static Window GetWindow()
      {
         var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsFocused);
         if (window == null)
            window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsVisible);
         if (window == null)
            window = Application.Current.MainWindow;
         return window;
      }
#endif
   }
}
